/*
This file is part of buco.  
Copyright (c) 2012 Christopher Pawelzik <christopher@cpawelzik.com>

Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 
*/ 
package buco.filemanagement;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.Map.Entry;
import java.util.zip.*;

/**
 * @author Christopher
 *
 */
public class FileManager {

	Path rootPath; 
	HashMap<Integer, File> files;
	int fileCounter = 0;
		
	public FileManager(String baseDir) throws IOException {
		Path basePath = Paths.get(baseDir); 	
		if(!basePath.toFile().exists()) {
			basePath = Paths.get(System.getProperty("java.io.tmpdir"));
		}
		rootPath = Files.createTempDirectory(basePath, "bucoFileManTemp");		
		files = new HashMap<Integer, File>(); 
	}

	public int addFile(String name, File file) throws IOException {
		byte[] data = new byte[(int)file.length()];
		FileInputStream fis;
		try {
			fis = new FileInputStream(file);
			fis.read(data);
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();		
		} catch (IOException e) {			
			e.printStackTrace();
		} 
		
		return addFile(name, data);
	}

	public File getFileByID(int id) {
		Integer key = new Integer(id); 
		if(files.containsKey(key)) { 
			return files.get(key); 			
		}
		return null;
	}

	public List<FileInfo> getFiles() {
		ArrayList<FileInfo> list = new ArrayList<FileInfo>(); 
		Iterator<Entry<Integer, File>> it = files.entrySet().iterator();
		while(it.hasNext()) {
			Entry<Integer, File> entry = it.next(); 
			Integer key = entry.getKey(); 
			File file = entry.getValue(); 			
			list.add(new FileInfo(key, file)); 
		}
		return list;
	}

	public void deleteAll() {
		for(FileInfo fileInfo : getFiles()) {
			fileInfo.getFile().delete();
		}
		
		// Delete deployment if it exists. 
		File deployment = new File(rootPath.toFile(), "deployment.zip"); 
		if(deployment.exists())  {
			deployment.delete();
		}
		
		rootPath.toFile().delete();		
	}

	public File createDeployment(List<Integer> files) {
		return makeExport(files, "deployment.zip", null); 
	}
	
	public File createExport(List<Integer> files, String compositionJson) {
		return makeExport(files, "export.zip", compositionJson); 
	}
	
	private File makeExport(List<Integer> files, String fileName, String compositionJson) {
		File zipFile = new File(rootPath.toFile(), fileName);		
		byte[] buffer = new byte[1024];
		
		try {
			ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream(zipFile.getAbsolutePath()));					
			for(int i = 0; i < files.size(); i++) { 				 			
				File file = getFileByID(files.get(i)); 	
				
				FileInputStream in = new FileInputStream(file);
				// Create zip entry
			    zipStream.putNextEntry(new ZipEntry(file.getName()));
				 
			    // Write file contents
			    int len;
	            while ((len = in.read(buffer)) > 0) {
	                zipStream.write(buffer, 0, len);
	            }
	            
	            zipStream.closeEntry();
	            in.close();
			}
			
			// Write composition data
			if(compositionJson != null) {
				zipStream.putNextEntry(new ZipEntry("composition.json"));
				zipStream.write(compositionJson.getBytes("UTF8"));
				zipStream.closeEntry();
			}
			
			zipStream.close(); 			
		} catch (FileNotFoundException e) { 
			e.printStackTrace();		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return zipFile;
	}

	public void deleteFile(int id) {
		if(!files.containsKey(id))  
			return; 
		
		File file = files.get(id);
		file.delete(); 
		files.remove(id); 		
	}
	
	public int addFile(String name, byte[] content) throws IOException {
		File file = new File(rootPath.toFile(), name); 
		FileOutputStream fos = new FileOutputStream(file);
		fos.write(content); 
		fos.close(); 		
		fileCounter++; 
		files.put(fileCounter, file);		
		return fileCounter;
	}
	
}
